package com.company.nuwa.mybatis.generator.plugins;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.mybatis.generator.api.*;
import org.mybatis.generator.api.dom.java.*;
import org.mybatis.generator.internal.types.JavaTypeResolverDefaultImpl;
import org.mybatis.generator.internal.util.StringUtility;

import java.sql.Types;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>注释插件</p>
 *
 * @author Lionel Lee
 * @version 1.0: Comment2Plugin.java
 * @date 2021/5/3  21:19
 */
public class Comment2Plugin extends PluginAdapter {
    @Override
    public boolean validate(List<String> list) {
        return true;
    }

    @Override
    public boolean modelBaseRecordClassGenerated(TopLevelClass topLevelClass,
                                                 IntrospectedTable introspectedTable) {
        //添加domain的import
        topLevelClass.addImportedType("lombok.Data");
        topLevelClass.addImportedType("lombok.experimental.Accessors");
        topLevelClass.addImportedType("com.fasterxml.jackson.annotation.JsonIgnoreProperties");
        topLevelClass.addImportedType("com.fasterxml.jackson.annotation.JsonFormat");
        //添加domain的注解
        topLevelClass.addAnnotation("@Data");
        topLevelClass.addAnnotation("@Accessors(chain = true)");
        topLevelClass.addAnnotation("@JsonIgnoreProperties(ignoreUnknown = true)");
        topLevelClass.addJavaDocLine("/**");

        String remarks = introspectedTable.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                topLevelClass.addJavaDocLine(" * <p>" + remarkLine + "</p>");
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(" * @author ").append(System.getProperties().getProperty("user.name"));
        topLevelClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * ").append("@version 1.0:")
            .append(introspectedTable.getFullyQualifiedTable().getDomainObjectName())
            .append(".java");
        topLevelClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * @date ");
        sb.append(getDateString());
        topLevelClass.addJavaDocLine(sb.toString());
        topLevelClass.addJavaDocLine(" */");
        return true;
    }

    @Override
    public boolean modelExampleClassGenerated(TopLevelClass topLevelClass,
                                              IntrospectedTable introspectedTable) {
        topLevelClass.addJavaDocLine("/**");

        String remarks = introspectedTable.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                topLevelClass.addJavaDocLine(" * <p>" + remarkLine + "</p>");
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(" * @author ").append(System.getProperties().getProperty("user.name"));
        topLevelClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * ").append("@version 1.0:")
            .append(introspectedTable.getFullyQualifiedTable().getDomainObjectName())
            .append("Example").append(".java");
        topLevelClass.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * @date ");
        sb.append(getDateString());
        topLevelClass.addJavaDocLine(sb.toString());
        topLevelClass.addJavaDocLine(" */");
        return true;
    }

    @Override
    public boolean modelFieldGenerated(Field field, TopLevelClass topLevelClass,
                                       IntrospectedColumn introspectedColumn,
                                       IntrospectedTable introspectedTable,
                                       ModelClassType modelClassType) {
        field.addJavaDocLine("/**");
        String remarks = introspectedColumn.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                field.addJavaDocLine(" * " + remarkLine);
            }
        }
        field.addJavaDocLine(" */");
        if (introspectedColumn.getJdbcType() == Types.TIME) {
            field.addAnnotation(
                "@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = \"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\")");
        }
        if (introspectedColumn.getJdbcType() == Types.TIMESTAMP) {
            field.addAnnotation(
                "@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = \"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\")");
        }
        if (introspectedColumn.getJdbcType() == Types.DATE) {
            field.addAnnotation(
                "@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = \"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\")");
        }
        if (introspectedColumn.getJdbcType() == Types.DATE) {
            field.addAnnotation(
                "@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = \"yyyy-MM-dd HH:mm:ss\", timezone = \"GMT+8\")");
        }

        return true;
    }

    @Override
    public boolean clientGenerated(Interface interfaze, IntrospectedTable introspectedTable) {
        //添加Mapper的import
        interfaze
            .addImportedType(new FullyQualifiedJavaType("org.apache.ibatis.annotations.Mapper"));
        //添加Mapper的注解
        interfaze.addAnnotation("@Mapper");
        interfaze.addImportedType(
            new FullyQualifiedJavaType("com.company.beauty.domain.mapper.BaseMapper"));
        /* interfaze.addSuperInterface(new FullyQualifiedJavaType(
            "com.company.beauty.domain.mapper.BaseMapper<" + introspectedTable
                .getFullyQualifiedTable().getDomainObjectName() + ">"));
        */
        JavaTypeResolver javaTypeResolver = new JavaTypeResolverDefaultImpl();
        FullyQualifiedJavaType calculateJavaType = javaTypeResolver
            .calculateJavaType(introspectedTable.getPrimaryKeyColumns().get(0));

        FullyQualifiedJavaType superInterfaceType = new FullyQualifiedJavaType(
            new StringBuilder("BaseMapper<").append(introspectedTable.getBaseRecordType())
                .append(",").append(introspectedTable.getExampleType()).append(",")
                .append(calculateJavaType.getShortName()).append(">").toString());
        FullyQualifiedJavaType baseMapperInstance = FullyQualifiedJavaTypeProxyFactory
            .getBaseMapperInstance();

        interfaze.addSuperInterface(superInterfaceType);
        interfaze.addImportedType(baseMapperInstance);

        List<Method> changeMethods = interfaze.getMethods().stream().filter(
            method -> method.getName().endsWith("WithBLOBs")
                      || method.getReturnType().toString().endsWith("WithBLOBs")
                      || Arrays.toString(method.getParameters().toArray()).contains("WithBLOBs"))
            .collect(Collectors.toList());

        interfaze.getMethods().retainAll(changeMethods);

        if (changeMethods.isEmpty()) {
            interfaze.getImportedTypes().removeIf(
                javaType -> javaType.getFullyQualifiedName().equals("java.util.List") || javaType
                    .getFullyQualifiedName().equals("org.apache.ibatis.annotations.Param"));
        }

        interfaze.addJavaDocLine("/**");

        String remarks = introspectedTable.getRemarks();
        if (StringUtility.stringHasValue(remarks)) {
            String[] remarkLines = remarks.split(System.getProperty("line.separator"));
            for (String remarkLine : remarkLines) {
                interfaze.addJavaDocLine(" * <p>" + remarkLine + "</p>");
            }
        }

        StringBuilder sb = new StringBuilder();
        sb.append(" * @author ").append(System.getProperties().getProperty("user.name"));
        interfaze.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * ").append("@version 1.0:")
            .append(introspectedTable.getFullyQualifiedTable().getDomainObjectName())
            .append("Mapper").append(".java");
        interfaze.addJavaDocLine(sb.toString());
        sb.setLength(0);
        sb.append(" * @date ");
        sb.append(getDateString());
        interfaze.addJavaDocLine(sb.toString());
        interfaze.addJavaDocLine(" */");
        return true;
    }

    @Override
    public boolean clientCountByExampleMethodGenerated(Method method, Interface interfaze,
                                                       IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 统计记录数");
        method.addJavaDocLine("* @param example 查询条件");
        method.addJavaDocLine("* @return long");
        method.addJavaDocLine(" */");
        return super.clientCountByExampleMethodGenerated(method, interfaze, introspectedTable);
    }

    @Override
    public boolean clientDeleteByExampleMethodGenerated(Method method, Interface interfaze,
                                                        IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 删除记录");
        method.addJavaDocLine("* @param example 查询条件");
        method.addJavaDocLine("* @return long");
        method.addJavaDocLine(" */");
        return super.clientDeleteByExampleMethodGenerated(method, interfaze, introspectedTable);
    }

    @Override
    public boolean clientDeleteByPrimaryKeyMethodGenerated(Method method, Interface interfaze,
                                                           IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 删除记录");
        method.addJavaDocLine("* @param id 主键");
        method.addJavaDocLine("* @return long");
        method.addJavaDocLine(" */");
        return super.clientDeleteByPrimaryKeyMethodGenerated(method, interfaze, introspectedTable);
    }

    @Override
    public boolean clientInsertMethodGenerated(Method method, Interface interfaze,
                                               IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 插入记录");
        method.addJavaDocLine("* @param record 记录");
        method.addJavaDocLine("* @return long");
        method.addJavaDocLine(" */");
        return super.clientInsertMethodGenerated(method, interfaze, introspectedTable);
    }

    @Override
    public boolean clientInsertSelectiveMethodGenerated(Method method, Interface interfaze,
                                                        IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 插入记录");
        method.addJavaDocLine("* @param record 记录");
        method.addJavaDocLine("* @return long");
        method.addJavaDocLine(" */");
        return true;
    }

    @Override
    public boolean clientSelectByPrimaryKeyMethodGenerated(Method method, Interface interfaze,
                                                           IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 删除记录");
        method.addJavaDocLine("* @param example 查询条件");
        method.addJavaDocLine(
            "* @return " + introspectedTable.getFullyQualifiedTable().getDomainObjectName());
        method.addJavaDocLine(" */");
        return true;
    }

    @Override
    public boolean clientSelectByExampleWithBLOBsMethodGenerated(Method method, Interface interfaze,
                                                                 IntrospectedTable introspectedTable) {
        return super.clientSelectByExampleWithBLOBsMethodGenerated(method, interfaze,
            introspectedTable);
    }

    @Override
    public boolean clientUpdateByPrimaryKeySelectiveMethodGenerated(Method method,
                                                                    Interface interfaze,
                                                                    IntrospectedTable introspectedTable) {
        method.addAnnotation("@Override");
        method.addJavaDocLine("/**");
        method.addJavaDocLine("* 更新记录");
        method.addJavaDocLine("* @param record 记录");
        method.addJavaDocLine(
            "* @return " + introspectedTable.getFullyQualifiedTable().getDomainObjectName());
        method.addJavaDocLine(" */");
        return true;
    }


    @Override
    public boolean modelSetterMethodGenerated(Method method, TopLevelClass topLevelClass,
                                              IntrospectedColumn introspectedColumn,
                                              IntrospectedTable introspectedTable,
                                              ModelClassType modelClassType) {
        //不生成getter
        return false;
    }

    @Override
    public boolean modelGetterMethodGenerated(Method method, TopLevelClass topLevelClass,
                                              IntrospectedColumn introspectedColumn,
                                              IntrospectedTable introspectedTable,
                                              ModelClassType modelClassType) {
        //不生成setter
        return false;
    }

    @Override
    public boolean sqlMapGenerated(GeneratedXmlFile sqlMap, IntrospectedTable introspectedTable) {
        //重新生成代码,xml内容覆盖
        sqlMap.setMergeable(false);
        return super.sqlMapGenerated(sqlMap, introspectedTable);
    }

    protected String getDateString() {
        return DateFormatUtils.format(new Date(), "yyyy-MM-dd HH:mm:ss");
    }

}